﻿using System.Windows;
using System.Collections.Generic;
using System;
using System.Xml.Linq;
using GameEngine.Libs;

namespace GameEngine.Model.Data
{
    public class WorldVO<ThingVOId> : IWorldVO<ThingVOId>
        where ThingVOId : IComparable<ThingVOId>
    {
        //Properties:

        public IWorldVOId Id { get; protected set; }
        public string Name { get; set; }
        
        //Containers:

        public List<IThingVO<ThingVOId>> Items { get; set; }
        public IMapVO<ThingVOId> Map { get; set; }

        public WorldVO(IWorldVOId id)
        {
            Id = id;
            Name = id.Value;
            Initialize();
        }

        public WorldVO() {
            Initialize();
        }

        public void Initialize() {
            Items = new List<IThingVO<ThingVOId>>();
        }

        public virtual string Serialize()
        {
            //return Serializer.Serialize(VO);
            XDocument doc = new XDocument();
            XElement mainNode = new XElement("WorldVO");
            mainNode.SetAttributeValue("Class", GetType());

            {
                XElement node = new XElement("Id", new XAttribute("Class", Id.GetType())) { Value = Id.Value };
                mainNode.Add(node);
            }
            {
                XElement node = new XElement("Name") { Value = Name };
                mainNode.Add(node);
            }
            {
                XElement node = new XElement("Items");
                foreach (var row in Items)
                {
                    XElement rowXml = new XElement("Item", new XAttribute("Class", row.GetType()));
                    rowXml.Add(row.Serialize());
                    node.Add(rowXml);
                }
                mainNode.Add(node);
            }
            {
                XElement node = new XElement("Map", new XAttribute("Class", Map.GetType()));
                node.Add(Map.Serialize());
                mainNode.Add(node);
            }
            return mainNode.ToString();
        }

        public virtual void DeSerialize(string serializedString)
        {
            XElement mainNode = XElement.Parse(serializedString);
            foreach (XElement node in mainNode.Nodes())
            {
                switch (node.Name.LocalName)
                {
                    case "Name":
                        Name = node.Value;
                        break;
                    case "Id":
                        {
                            var className = node.Attribute("Class").Value;
                            var classType = Serializer.GetType(className);
                            Id = Activator.CreateInstance(classType,node.Value) as IWorldVOId;
                        }
                        break;
                    case "Items":
                        {
                            foreach (var row in node.Elements())
                            {
                                var className = row.Attribute("Class").Value;
                                var classType = Serializer.GetType(className);
                                var instance = Activator.CreateInstance(classType) as IThingVO<ThingVOId>;
                                instance.DeSerialize(row.Value);
                                Items.Add(instance);
                            }
                        }
                        break;
                    case "Map":
                        {
                            var className = node.Attribute("Class").Value;
                            var classType = Type.GetType(className);
                            var instance = Activator.CreateInstance(classType) as IMapVO<ThingVOId>;
                            instance.DeSerialize(node.Value);
                            Map = instance;
                        }
                        break;
                }
            }
        }
    }

    public class WorldVOId : SimpleId<string> ,IWorldVOId {
        public WorldVOId(string id):base(id){}
        public WorldVOId() { }
    }
}